package com.shu.juc;

import lombok.extern.slf4j.Slf4j;

import java.lang.management.ManagementFactory;
import java.lang.management.ThreadInfo;
import java.lang.management.ThreadMXBean;

/**
 * @author ssm
 * @version V1.0
 * @description: 死锁
 * @date 2020/7/31 17:43
 */
@Slf4j
public class MustDeadLock implements Runnable {

    static Object o1 = new Object();
    static Object o2 = new Object();
    public int flag;

    public static void main(String[] args) throws InterruptedException {
        MustDeadLock m1 = new MustDeadLock();
        MustDeadLock m2 = new MustDeadLock();

        m1.flag = 1;
        m2.flag = 2;

        new Thread(m1).start();
        new Thread(m2).start();


        Thread.sleep(3000);

        log.info("主线程执行完毕");


        // 使用 ThreadMXBean 检测死锁
        ThreadMXBean threadMXBean = ManagementFactory.getThreadMXBean();
        long[] deadlockedThreads = threadMXBean.findDeadlockedThreads();
        if (deadlockedThreads != null && deadlockedThreads.length > 0) {
            for (int i = 0; i < deadlockedThreads.length; i++) {
                ThreadInfo threadInfo = threadMXBean.getThreadInfo(deadlockedThreads[i]);
                System.out.println("线程id为" + threadInfo.getThreadId() + ",线程名为" + threadInfo.getThreadName() + "的线程已经发生死锁，需要的锁正被线程" + threadInfo.getLockOwnerName() + "持有。");
            }
        }
    }

    @Override
    public void run() {
        log.info("---");
        if (flag == 1) {
            synchronized (o1) {
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }

                synchronized (o2) {
                    log.info("获取锁成功");
                }
            }
        }

        if (flag == 2) {
            synchronized (o2) {
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }

                synchronized (o1) {
                    log.info("获取锁成功");
                }
            }
        }
    }
}
